﻿using Shapefile;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ShapeFileViewer
{
    public partial class MainForm : Form
    {
        // 用于管理打开的多个Shape文件
        List<ShapeFile> shpList = new List<ShapeFile>();
        System.Drawing.Drawing2D.Matrix transform = new System.Drawing.Drawing2D.Matrix();
        PointF mouse_pos = new PointF();

        public MainForm()
        {
            //设置窗体的双缓冲
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
            UpdateStyles();

            InitializeComponent();

            // 利用反射设置DataGridView的双缓冲（解决DataGridView显示卡顿问题）
            Type dgvType = dbfdataGridView.GetType();
            PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
                BindingFlags.Instance | BindingFlags.NonPublic);
            pi.SetValue(dbfdataGridView, true, null);
            this.DrawPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.DrawPanel_Paint);
            this.DrawPanel.MouseClick += new MouseEventHandler(DrawPanel_MouseClick);
            this.DrawPanel.MouseMove += new MouseEventHandler(DrawPanel_MouseMove);
            this.DrawPanel.MouseUp += new MouseEventHandler(DrawPanel_MouseUp);
            this.DrawPanel.MouseDoubleClick += new MouseEventHandler(DrawPanel_MouseDoubleClick);

            this.layerManager.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.layerManager_AfterCheck);

            this.DrawPanel.MouseWheel += new MouseEventHandler(DrawPanel_MouseWheel);

            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }

        private void 打开Shape文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.DefaultExt = "shp";
            fileDialog.Filter = "Shape files (*.shp)|*.shp|All files (*.*)|*.*";
            fileDialog.InitialDirectory = Application.StartupPath;
            fileDialog.RestoreDirectory = true;
            fileDialog.ShowDialog();

            shpfilePath.Text = fileDialog.FileName;

        }

        private void shpfilePath_TextChanged(object sender, EventArgs e)
        {

        }

        private void browseShpBtn_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.DefaultExt = "shp";
            fileDialog.Filter = "Shape files (*.shp)|*.shp|All files (*.*)|*.*";
            fileDialog.InitialDirectory = Application.StartupPath;
            fileDialog.RestoreDirectory = true;
            fileDialog.ShowDialog();

            shpfilePath.Text = fileDialog.FileName;
        }

        private void openShpBtn_Click(object sender, EventArgs e)
        {
            string filepath = shpfilePath.Text;
            if (filepath.Length == 0) return;
            if (Path.GetExtension(filepath) != ".shp") return;

            ShapeFile shapefile = new ShapeFile(filepath);
            shpList.Add(shapefile);
            InitScale();
            shapefile.IsRender = true;
            AddLayer(shapefile.FileName);
            DrawPanel.Refresh();

            dbfdataGridView.DataSource = shapefile.DataSet.Tables[0];
        }

        private void AddLayer(string layerName)
        {
            layerManager.BeginUpdate();
            TreeNode treenode = new TreeNode(layerName);
            treenode.Checked = true;
            layerManager.Nodes.Add(treenode);
            layerManager.EndUpdate();

        }

        private void layerManager_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Action != TreeViewAction.Unknown)
            {
                shpList[e.Node.Index].IsRender = e.Node.Checked;
                DrawPanel.Refresh();
            }
        }

        private void DrawPanel_Paint(object sender, PaintEventArgs e)
        {
            if (shpList.Count <= 0) return; // 在没有读入数据时，不需要绘制图形

            Graphics g = e.Graphics;
            g.Clear(Color.White);
            g.Transform = transform;

            for (int i = 0; i < shpList.Count; i++)
                if (shpList[i].IsRender)
                    foreach (var shape in shpList[i])
                        shape.Render(g);


        }

        private void browseMifBtn_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Mif files (*.mif)|*.mif|All files (*.*)|*.*";
            saveFileDialog.Title = "选择保存文件";
            saveFileDialog.InitialDirectory = Application.StartupPath;
            saveFileDialog.RestoreDirectory = true;
            saveFileDialog.ShowDialog();

            mifPath.Text = saveFileDialog.FileName;
        }

        private void saveMifBtn_Click(object sender, EventArgs e)
        {
            string savePath = mifPath.Text;
            if (savePath.Length == 0) return;
            if (shpList.Count == 0) return;

            shpList.ElementAt(0).SaveAsMif(savePath);

            MessageBox.Show("保存成功");

        }
        private void DrawPanel_MouseWheel(object sender, MouseEventArgs e)
        {
            if (shpList.Count > 0)
            {
                PointF now_pos = new PointF(e.X, e.Y);
                PointF[] pos = new PointF[1];
                pos[0] = now_pos;
                var trans_inv = transform.Clone();
                trans_inv.Invert();
                trans_inv.TransformPoints(pos);
                if (e.Delta > 0)
                    transform.Scale(e.Delta / 100f, e.Delta / 100f);
                else
                    transform.Scale(-100f / e.Delta, -100f / e.Delta);
                PointF[] pos_scale = new PointF[1];
                pos_scale[0] = now_pos;
                trans_inv = transform.Clone();
                trans_inv.Invert();
                trans_inv.TransformPoints(pos_scale);
                float dx = pos_scale[0].X - pos[0].X;
                float dy = pos_scale[0].Y - pos[0].Y;
                transform.Translate(dx, dy);
                DrawPanel.Refresh();
            }
        }

        private void DrawPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (shpList.Count != 0)
            {
                PointF now_pos = new PointF(e.X, e.Y);
                PointF[] pos_coord = new PointF[1];
                pos_coord[0] = now_pos;
                if (e.Button == MouseButtons.Left)
                {
                    this.Cursor = Cursors.Hand;
                    PointF[] pos = new PointF[2];
                    pos[0] = mouse_pos;
                    pos[1] = now_pos;
                    var trans_inv = transform.Clone();
                    trans_inv.Invert();
                    trans_inv.TransformPoints(pos);
                    float dx = pos[1].X - pos[0].X;
                    float dy = pos[1].Y - pos[0].Y;
                    transform.Translate(dx, dy);
                    DrawPanel.Refresh();
                }
                var trans_inv1 = transform.Clone();
                trans_inv1.Invert();
                trans_inv1.TransformPoints(pos_coord);
                coorStatusLabel.Text = "当前X、Y坐标：" + pos_coord[0].X + ", " + pos_coord[0].Y;
            }
            mouse_pos = new PointF(e.X, e.Y);
        }
        private void DrawPanel_MouseClick(object sender, MouseEventArgs e)
        {

        }

        private void DrawPanel_MouseUp(object sender, MouseEventArgs e)
        {
            this.Cursor = Cursors.Default;
        }

        private void DrawPanel_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            InitScale();
            DrawPanel.Refresh();
        }

        private void InitScale()
        {
            float w = DrawPanel.Width;
            float h = DrawPanel.Height;
            float max_left = Convert.ToSingle(shpList[0].BoundingBox.Left);
            float max_right= Convert.ToSingle(shpList[0].BoundingBox.Right);
            float max_top = Convert.ToSingle(shpList[0].BoundingBox.Top);
            float max_bottom= Convert.ToSingle(shpList[0].BoundingBox.Bottom);
            for (int i = 1; i < shpList.Count; i++)
            {
                if (shpList[i].BoundingBox.Left < max_left)
                    max_left = Convert.ToSingle(shpList[i].BoundingBox.Left);
                if (shpList[i].BoundingBox.Right > max_right)
                    max_right = Convert.ToSingle(shpList[i].BoundingBox.Right);
                if (shpList[i].BoundingBox.Bottom < max_bottom)
                    max_bottom = Convert.ToSingle(shpList[i].BoundingBox.Bottom);
                if (shpList[i].BoundingBox.Top > max_top)
                    max_top = Convert.ToSingle(shpList[i].BoundingBox.Top);
            }

            float data_width = max_right - max_left;
            float data_height = max_top - max_bottom;
            float sx = w / (data_width * 1.02f);
            float sy = h / (data_height * 1.02f);
            float dx = 0.0f;
            float dy = 0.0f;
            if (sx > sy)
            {
                sx = sy;
                dx = (data_width - w / sx) / 2.0f; // 调整横向比例，横向居中
            }
            else
            {
                sy = sx;
                dy = (data_height - h / sy) / 2.0f; // 调整纵向比例，纵向居中
            }
            Matrix new_trans = new Matrix();

            new_trans.Scale(sx, -sy);
            new_trans.Translate(-max_left + data_width * 0.01f - dx,
                -max_top - data_height * 0.01f + dy);
            transform = new_trans;
        }
    }
}
